﻿using System.Text;

namespace MonoMod.SourceGen.Internal
{
    internal sealed class CodeBuilder
    {
        private readonly StringBuilder sb;
        private readonly char indentChar = ' ';
        private readonly int indentAmount;

        public CodeBuilder(StringBuilder sb, int indentAmount = 4)
        {
            this.sb = sb;
            this.indentAmount = indentAmount;
        }

        private int indentLevel;
        private bool didWriteIndent;

        public CodeBuilder WriteHeader()
        {
            WriteLine("// <auto-generated />");
            WriteLine("#nullable enable");
            return this;
        }

        public CodeBuilder OpenBlock()
            => WriteLine('{').IncreaseIndent();
        public CodeBuilder CloseBlock()
            => DecreaseIndent().WriteLine('}');

        public CodeBuilder IncreaseIndent()
        {
            indentLevel++;
            return this;
        }

        public CodeBuilder DecreaseIndent()
        {
            indentLevel--;
            return this;
        }

        private void WriteIndentIfNeeded()
        {
            if (didWriteIndent)
            {
                return;
            }

            if (indentLevel > 0)
            {
                sb.Append(indentChar, indentLevel * indentAmount);
            }
            didWriteIndent = true;
        }

        public CodeBuilder Write(string s)
        {
            WriteIndentIfNeeded();
            sb.Append(s);
            return this;
        }

        public CodeBuilder Write(char c)
        {
            WriteIndentIfNeeded();
            sb.Append(c);
            return this;
        }

        public CodeBuilder WriteLine(string s)
        {
            WriteIndentIfNeeded();
            sb.AppendLine(s);
            didWriteIndent = false;
            return this;
        }

        public CodeBuilder WriteLine(char c)
        {
            WriteIndentIfNeeded();
            sb.Append(c).AppendLine();
            didWriteIndent = false;
            return this;
        }

        public CodeBuilder WriteLine()
        {
            sb.AppendLine();
            didWriteIndent = false;
            return this;
        }
    }
}
